Program debugging, or debugging, is a methodical process of finding and reducing the number of bugs, or defects, in a computer program or a piece of electronic hardware to make the computer program behave as expected. Debugging in general is a lengthy, tiresome task, and programmers often use a software tool such as a debugger operating on a debuggee process to monitor execution of the computer program and to perform program debugging. During investigation of the program, the programmer may stop the execution of the debuggee process, collect data values, or otherwise affect the execution of the debuggee process based on the values of the variables. The program may know the points of investigation and build the logic into the program, or the programmer can make use of the debugger to place instrumentation.
The use of the debugger can provide difficulties in program debugging. For example, the range of possible instrumentation varies depending on the debugger used, and thus the programmer will use care to select the correct debugger if one even exists. Further, the cost—in terms of delayed execution while the instrumentation is evaluated—is often prohibitive because the delayed execution with the debugger is often several orders of magnitude slower than if the programmer had built the same instrumentation into the program. In many cases, the programmer will often choose to exit the debugger and modify the computer program rather than make use of the instrumentation features of the debugger.
Previous attempts to address these difficulties have included using breakpoints and debugger/debuggee communications with operating system facilities to provide instrumentation. The debugger is involved at every execution of the instrumentation. Program debuggers often allow the programmer to specify instrumentation points (such as conditional breakpoints, tracepoints, or the like) and a description to address ad hoc needs in the debugging process. The debugger implements these points based on the instrumentation point capability of the debugger. The debugger places an instrumentation point, such as a software interrupt instruction, into the program code of the debuggee process. When the debuggee executes the interrupt, the operating system pauses the execution of the debuggee process and notifies the debugger. The debugger executes the behavior specified in the instrumentation point description. For example, in the case of a conditional breakpoint, the debugger evaluates the conditional expression. Because these expressions often refer to program variables, the debugger makes call to the operating system to read the memory contents of the debuggee process and extract the variable values. If the condition evaluates true then the debugger notifies the programmer. Otherwise, the debugger notifies the operating system that then continues the execution of the debuggee process.
This course of pausing the debuggee process, executing the debugger, querying the debugger state, and continuing the execution of the debuggee process requires the execution of a relatively large amount of code. Further, specifying this instrumentation at a program location that executes frequently can cause a relatively large perturbation in the execution of the debuggee process even if the condition is never true. This often makes a conditional breakpoint feature impractical to use.